package com.example.administrator.gplineview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator
 * Created on 2017/4/18
 */

public class RoundPercentView extends View {
    private List<Paint> mPaints;
    private List<String> mContents;
    private List<Float> mPercents;
    private int mHeight;
    private int mWidth;
    private int mRadius;
    private RectF mRectF;
    private Paint mPaint;
    private float mTouchX;
    private float mTouchY;
    private int mCurrentIndex = -1;
    private int mPreIndex = -2;
    private Point mCirCenter;
    private List<Point> mArcs;
    private RectF mCheckRectF;
    private int mLarger;

    public RoundPercentView(Context context) {
        this(context, null);
    }

    public RoundPercentView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundPercentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaints = new ArrayList<>();
        mContents = new ArrayList<>();
        mPercents = new ArrayList<>();
        mArcs = new ArrayList<>();

        mPaint = new Paint();
        mPaint.setColor(Color.GRAY);
        mPaint.setAntiAlias(true);
        mCirCenter = new Point();

        mTracker = VelocityTracker.obtain();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //拿到测量后的宽高
        mHeight = getMeasuredHeight();
        mWidth = getMeasuredWidth();
        //设置圆形的属性
        mRadius = Math.min(mHeight, mWidth) / 2;
        //设置圆心点
        mCirCenter.setxLoc(mWidth / 2);
        mCirCenter.setyLoc(mHeight / 2);
        //初始圆形所在矩形
        mRectF = new RectF(mWidth / 2 - mRadius + 3 * mLarger, mHeight / 2 - mRadius + 3 * mLarger, mWidth / 2 + mRadius - 3 * mLarger, mHeight / 2 + mRadius - 3 * mLarger);
        mLarger = DensityUtils.dp2px(getContext(), 5);
        //点击后的那部分所在矩形，比之前的略大
        mCheckRectF = new RectF(mWidth / 2 - mRadius + 2.5f * mLarger, mHeight / 2 - mRadius + 2.5f * mLarger, mWidth / 2 + mRadius - 2.5f * mLarger, mHeight / 2 + mRadius - 2.5f * mLarger);
    }

    /**
     * 使用之前先调用该方法初始化内容；三个集合数量要相等
     *
     * @param percents 占据的百分比集合
     * @param contents 数据内容集合
     * @param colors   扇形颜色集合
     */
    public void setData(List<Float> percents, List<String> contents, List<Integer> colors) throws Exception {
        if (percents.size() != contents.size()) {
            throw new Exception("百分比集合的大小和内容集合以及颜色集合必须一致");
        }
        if (percents.size() != colors.size()) {
            throw new Exception("百分比集合的大小和内容集合以及颜色集合必须一致");
        }
        int angle = 0;
        mContents = contents;
        mPercents = percents;
        for (int i = 0; i < colors.size(); i++) {
            Paint paint = new Paint();
            paint.setColor(colors.get(i));
            paint.setAntiAlias(true);
            paint.setTextSize(DensityUtils.sp2px(getContext(), 11));
            mPaints.add(paint);
            mArcs.add(new Point(angle, angle + mPercents.get(i) / 100.0f * 360f));
            angle += mPercents.get(i) / 100.0f * 360f;
        }
        postInvalidate();
    }

    private boolean hasMoved;
    private double mCurrentTouchAngle;
    private double mPreTouchAngle = -1;
    private double mDAngle;
    private VelocityTracker mTracker;
    private double mVelocity;
    private final static double VELOCITY = 0.3;

    /**
     * 触摸事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mTouchX = event.getX();     //触摸点横坐标
        mTouchY = event.getY();     //触摸点纵坐标
        mCurrentTouchAngle = getAngle(mTouchX, mTouchY, mCirCenter.getxLoc(), mCirCenter.getyLoc());
        mTracker.addMovement(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                hasMoved = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if ((Math.pow(mTouchX - mCirCenter.getxLoc(), 2) + Math.pow(mTouchY - mCirCenter.getyLoc(), 2)) <= Math.pow(mRadius, 2)) {
                    if (mPreTouchAngle != -1) {
                        reset();
                        hasMoved = true;
                        mDAngle = mCurrentTouchAngle - mPreTouchAngle;
                        reload();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!hasMoved) {
                    if (setViewClick()) break;
                } else {
                    setViewTurn();
                }
                mTracker.clear();
                break;
        }
        mPreTouchAngle = mCurrentTouchAngle;
        return true;
    }

    private void setViewTurn() {
        mTracker.computeCurrentVelocity(100);
        mVelocity = Math.pow(mTracker.getXVelocity(), 2) + Math.pow(mTracker.getYVelocity(), 2);
        if (mVelocity > 1000) {
            mDAngle = Math.sqrt(mVelocity);
            if (mDAngle > 200){
                mDAngle = 20;
                postDelayed(action, 20);
            }else if (mDAngle > 100){
                mDAngle = 15;
                postDelayed(action, 20);
            }else if (mDAngle > 50){
                mDAngle = 10;
                postDelayed(action, 20);
            }
        }
    }

    private boolean setViewClick() {
        mCurrentIndex = getTouchViewIndex(mTouchX, mTouchY);
        if (mCurrentIndex == -1) return true;
        if (mCurrentIndex != mPreIndex) {
            postInvalidate();
            mPreIndex = mCurrentIndex;
        }
        return false;
    }

    private void reset(){
        mCurrentIndex = -1;
        mPreIndex = -1;
    }

    private Runnable action = new Runnable() {
        @Override
        public void run() {
            mDAngle -= VELOCITY;
            if (mDAngle <= 0){
                mDAngle = 0;
            }else {
                reload();
                postDelayed(action,20);
            }
        }
    };

    private void reload() {
        for (int i = 0; i < mArcs.size(); i++) {
            if ((mArcs.get(i).getXVal() + mDAngle) > 360){
                mArcs.get(i).setxVal((float) (mArcs.get(i).getXVal() + mDAngle - 360));
            }else if ((mArcs.get(i).getXVal() + mDAngle) < 0){
                mArcs.get(i).setxVal((float) (mArcs.get(i).getXVal() + mDAngle + 360));
            }else {
                mArcs.get(i).setxVal((float) (mArcs.get(i).getXVal() + mDAngle));
            }
            if ((mArcs.get(i).getYVal() + mDAngle) > 360){
                mArcs.get(i).setyVal((float) (mArcs.get(i).getYVal() + mDAngle - 360));
            }else if ((mArcs.get(i).getYVal() + mDAngle) < 0){
                mArcs.get(i).setyVal((float) (mArcs.get(i).getYVal() + mDAngle + 360));
            }else {
                mArcs.get(i).setyVal((float) (mArcs.get(i).getYVal() + mDAngle));
            }
        }
        postInvalidate();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mTracker.recycle();
    }

    /**
     * @param x 点的横坐标
     * @param y 点的纵坐标
     * @return 点在哪一个扇形内部
     */
    private int getTouchViewIndex(float x, float y) {
        int index = -1;
        if ((Math.pow(x - mCirCenter.getxLoc(), 2) + Math.pow(y - mCirCenter.getyLoc(), 2)) > Math.pow(mRadius, 2)) {
            return -1;
        }
        double angle = getAngle(mTouchX, mTouchY, mCirCenter.getxLoc(), mCirCenter.getyLoc());
        for (int i = 0; i < mArcs.size(); i++) {
            if (mArcs.get(i).getXVal() > mArcs.get(i).getYVal()){
                if (angle >= mArcs.get(i).getXVal() || angle <= mArcs.get(i).getYVal()) {
                    index = i;
                    break;
                }
            }else {
                if (angle >= mArcs.get(i).getXVal() && angle <= mArcs.get(i).getYVal()) {
                    index = i;
                    break;
                }
            }

        }
        return index;
    }

    /**
     * @param x  测量点的横坐标
     * @param y  测量点的纵坐标
     * @param cX 圆心横坐标
     * @param cY 圆心纵坐标
     * @return 点和圆心的连线与x轴构成的夹角度数（x轴正方向为0，顺时针递增）
     */
    private double getAngle(float x, float y, float cX, float cY) {
        if (x == cX && y == cY) return 0;
        if (x >= cX && y >= cY) {
            if (x == cX) return 90;
            return Math.toDegrees(Math.atan(Math.abs(y - cY) / Math.abs(x - cX)));
        }
        if (x >= cX && y <= cY) {
            if (x == cX) return 270;
            return 360 - Math.toDegrees(Math.atan(Math.abs(y - cY) / Math.abs(x - cX)));
        }
        if (x <= cX && y <= cY) {
            return 180 + Math.toDegrees(Math.atan(Math.abs(y - cY) / Math.abs(x - cX)));
        }
        if (x <= cX && y >= cY) {
            return 180 - Math.toDegrees(Math.atan(Math.abs(y - cY) / Math.abs(x - cX)));
        }
        return -1;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < mPercents.size(); i++) {
            if (i == mCurrentIndex) {
                //画选中的扇形图
                canvas.drawArc(mCheckRectF, mArcs.get(i).getXVal(), mPercents.get(i) / 100.0f * 360f, true, mPaints.get(i));
                //画文字
                canvas.drawText(mContents.get(i) + "\n" + mPercents.get(i) + "%",
                        mWidth / 2 - TextUtil.getTextWidth(mPaints.get(i), mContents.get(i) + "\n" + mPercents.get(i) + "%") / 2,
                        mHeight - DensityUtils.dp2px(getContext(), 2), mPaints.get(i));
            } else {
                //画未选中的扇形图
                canvas.drawArc(mRectF, mArcs.get(i).getXVal(), mPercents.get(i) / 100.0f * 360f, true, mPaints.get(i));
            }
        }
    }


    /**
     * 动态测高，适配
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        ViewGroup.LayoutParams lp = getLayoutParams();
        if (lp.width != ViewGroup.LayoutParams.MATCH_PARENT) {
            widthSize = (int) (widthSize * MyApplication.mScreenWidth / 320.0);
        }
        if (lp.height != ViewGroup.LayoutParams.MATCH_PARENT) {
            heightSize = (int) (heightSize * MyApplication.mScreenWidth / 480.0);
        }
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
